﻿//----------------------------------------------------------------
// Copyright (c) 2011-2013 
// All rights reserved.
// Author: Ben DaoWei 
// Contact: bendaowei@gmail.com
// Web Link: http://xnaeditor.codeplex.com
// ----------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using MdxLib.Model;
using Microsoft.Xna.Framework;
using UnityEngine.Graphics.Shader;

namespace UnityEngine.Graphics
{
    #region base class
    public class PaletteRenderer : IDisposable
    {
        public PaletteRenderer()
        {
            _ReferenceSet = new List<PaletteReference>();
        }

        ~PaletteRenderer()
        {
            this.Dispose(false);
        }

        public void Dispose()
        {
            this.Dispose(true);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                // do nothing
            }
        }

        private List<PaletteReference> _ReferenceSet;

        public List<PaletteReference> ReferenceSet
        {
            get { return _ReferenceSet; }
            set { _ReferenceSet = value; }
        }

        public virtual void Begin() { }
        public virtual void End() { }
    }
    #endregion

    #region 2D Graphics
    public class SpriteRenderer : PaletteRenderer
    {
        public SpriteBatch SpriteBatch
        {
            get { return _SpriteBatch; }
        }
        protected SpriteBatch _SpriteBatch;

        public SpriteRenderer(SpriteBatch spriteBatch)
        {
            _SpriteBatch = spriteBatch;
        }
    }

    public class CusmtomBlendSpriteRenderer : SpriteRenderer
    {
        private Effect _Effect;

        public CusmtomBlendSpriteRenderer(SpriteBatch spriteBatch, Game game)
            : base(spriteBatch)
        {
            Viewport viewport = EffectManager.Instance.GraphicsDevice.Viewport;
            Matrix projection = Matrix.CreateOrthographicOffCenter(0, viewport.Width, viewport.Height, 0, 0, 1);
            Matrix halfPixelOffset = Matrix.CreateTranslation(-0.5f, -0.5f, 0);

            this._Effect = game.Content.Load<Effect>("Shader\\CustomEffect");
        }

        public override void Begin()
        {
            _SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque, SamplerState.PointClamp, DepthStencilState.Default, RasterizerState.CullNone, _Effect);
        }

        public override void End()
        {
            _SpriteBatch.End();
        }

        public int Mode
        {
            set
            {
                this._Effect.Parameters["Mode"].SetValue(value);
            }
        }

        public float Percent
        {
            set
            {
                this._Effect.Parameters["Percent"].SetValue(value);
            }
        }

        public int Width
        {
            set
            {
                this._Effect.Parameters["Width"].SetValue(value);
            }
        }

        public int Height
        {
            set
            {
                this._Effect.Parameters["Height"].SetValue(value);
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _SpriteBatch.Dispose();
                _Effect.Dispose();
            }
        }
    }

    public class AlphaBlendSpriteRenderer : SpriteRenderer
    {
        public AlphaBlendSpriteRenderer(SpriteBatch spriteBatch)
            : base(spriteBatch)
        {
        }

        public override void Begin()
        {
            _SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied);
        }

        public override void End()
        {
            _SpriteBatch.End();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _SpriteBatch.Dispose();
            }
        }
    }

    public class OpaqueBlendSpriteRenderer : SpriteRenderer
    {
        public OpaqueBlendSpriteRenderer(SpriteBatch spriteBatch)
            : base(spriteBatch)
        {
            _SpriteBatch = spriteBatch;
        }

        public override void Begin()
        {
            _SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque);
        }

        public override void End()
        {
            _SpriteBatch.End();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _SpriteBatch.Dispose();
            }
        }
    }

    public class AlphaTestBlendSpriteRenderer : SpriteRenderer
    {
        private AlphaTestEffect _AlphaTestEffect;

        public AlphaTestBlendSpriteRenderer(SpriteBatch spriteBatch)
            : base(spriteBatch)
        {
            Viewport viewport = EffectManager.Instance.GraphicsDevice.Viewport;
            Matrix projection = Matrix.CreateOrthographicOffCenter(0, viewport.Width, viewport.Height, 0, 0, 1);
            Matrix halfPixelOffset = Matrix.CreateTranslation(-0.5f, -0.5f, 0);

            _AlphaTestEffect = new AlphaTestEffect(EffectManager.Instance.GraphicsDevice);
            _AlphaTestEffect.VertexColorEnabled = false;
            _AlphaTestEffect.DiffuseColor = Color.White.ToVector3();
            _AlphaTestEffect.AlphaFunction = CompareFunction.Greater;
            _AlphaTestEffect.ReferenceAlpha = 192;
            _AlphaTestEffect.World = Matrix.Identity;
            _AlphaTestEffect.View = Matrix.Identity;
            _AlphaTestEffect.Projection = halfPixelOffset * projection;
        }

        public override void Begin()
        {
            _SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque, SamplerState.PointClamp, DepthStencilState.Default, RasterizerState.CullNone, _AlphaTestEffect);
        }

        public override void End()
        {
            _SpriteBatch.End();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _SpriteBatch.Dispose();
                _AlphaTestEffect.Dispose();
            }
        }
    }
    #endregion


    #region 3D Graphics
    public class CliffRenderer : ModelRenderer
    {
        public CliffRenderer(GraphicsDevice graphicsDevice, CModel Model)
            : base(Model, graphicsDevice)
        {
        }

        public void UpdateCliff(Vector3[] Positions, bool IsCliffTrans, EDirection direction, ESide side, Matrix World)
        {
            foreach (GeosetRenderer GeosetRenderer in this.GeosetRenderers)
            {
                GeosetRenderer.UpdateCliff(Positions, IsCliffTrans, direction, side, World);
            }
        }

        public CliffRenderer Copy()
        {
            return new CliffRenderer(this.GraphicsDevice, this.Model);
        }
    }

    public class DoodadRenderer : ModelRenderer
    {
        public DoodadRenderer(GraphicsDevice graphicsDevice, CModel Model)
            : base(graphicsDevice, Model)
        {
        }
    }

    public class UnitRenderer : DoodadRenderer
    {
        public UnitRenderer(GraphicsDevice graphicsDevice, CModel Model)
            : base(graphicsDevice, Model)
        {
        }
    }
    #endregion
}
